package key

import (
	"fmt"
	"github.com/Exleryz/m3u8/internal/m3u8/parser/key/strategy"
	"github.com/Exleryz/m3u8/util"
	"os"
	"path"
	"strings"
)

type M3U8Key struct {
	// #EXT-X-KEY:之后的数据
	Line string
	// Method 加密方式
	Method  string
	URI     string
	KeyHex  string
	KeyInfo []byte
	IV      []byte
	Opt     strategy.M3U8KeyOpt
}

func NewM3U8Key(line string) *M3U8Key {
	// 解析
	fmt.Println("origin line:", line)
	line = strings.ReplaceAll(line, "#EXT-X-KEY:", "")
	split := strings.Split(line, ",")
	method := ""
	uri := ""
	// 填默认值
	//iv := "00000000000000000000000000000000"
	var iv []byte

	//  这个解析方法看着很蠢
	for i := range split {
		item := split[i]
		if m, ok := strings.CutPrefix(item, "METHOD="); ok {
			method = m
			fmt.Println("METHOD", method)
			if iv == nil {
				switch method {
				case "AES-128":
					iv = make([]byte, 16)
				case "AES-192":
					iv = make([]byte, 24)
				case "AES-256":
					iv = make([]byte, 32)
				}
			}
		} else if u, ok := strings.CutPrefix(item, "URI="); ok {
			u = strings.Trim(u, "\"")
			uri = u
			fmt.Println("URI", u)
		} else if iv_, ok := strings.CutPrefix(item, "IV="); ok {
			if strings.Index(iv_, "0x") == 0 {
				iv_ = strings.Replace(iv_, "0x", "", 1)
			}
			var err error
			iv, err = util.GetHexBytesByString(iv_)
			fmt.Println("IV", iv_, err)
		} else {
			fmt.Println("error 没有处理的 key:", item)
		}
	}

	// 初始化
	var opt strategy.M3U8KeyOpt = strategy.DefaultKeyDownload{}

	// 筛选
	if strings.Index(uri, "https://auth.zsxq.com") != -1 {
		opt = strategy.ZSXQStrategy{}
	}

	return &M3U8Key{
		Line:   line,
		Method: method,
		URI:    uri,
		IV:     iv,
		Opt:    opt,
	}
}

// DownloadKey 下载 key
func (key *M3U8Key) DownloadKey(dir string) (string, error) {
	// 这个获取 keyByte 由各自自己实现
	keyBytes, err := key.Opt.GetKeyBytes(key.URI)
	if err != nil {
		fmt.Println(err)
		return "", err
	}

	key.KeyInfo = keyBytes

	// 保存到本地
	keyFile, err := os.Create(path.Join(dir, "key"))
	if err != nil {
		fmt.Println(err)
		return "", err
	}
	defer keyFile.Close()
	_, err = keyFile.Write(keyBytes)
	if err != nil {
		return "", err
	}

	err = key.GenDecryptionShell(dir, keyBytes)
	if err != nil {
		return "", err
	}

	return key.KeyHex, nil
}

// 解密脚本模板

// BatchDecryptionTemplate 批量
const BatchDecryptionTemplate = `mkdir tmp
for ts_file in $(ls -al | grep .ts | awk '{print $NF}')
do
  echo "$ts_file"
  openssl aes-128-cbc -d -in "$ts_file" -out tmp/"$ts_file" -nosalt -K %s -iv %s
  rm -rf "$ts_file"
  cp tmp/"$ts_file" ./
done
rm -rf ./tmp
`

// SingleDecryptionTemplate 单个文件
const SingleDecryptionTemplate = `echo "$ts_file"
openssl aes-128-cbc -d -in "$ts_file" -out tmp/"$ts_file" -nosalt -K %s -iv %s
rm -rf "$ts_file"
cp tmp/"$ts_file" ./`

// GenDecryptionShell 生成解密脚本
func (key *M3U8Key) GenDecryptionShell(dir string, keyBytes []byte) error {
	key.KeyHex = util.GetHexStringByByte(keyBytes)
	// 解密
	batchDecryptionShell, err := os.Create(path.Join(dir, "batch_decryption.sh"))
	if err != nil {
		fmt.Println(err)
		return err
	}
	defer batchDecryptionShell.Close()

	singleDecryptionShell, err := os.Create(path.Join(dir, "single_decryption.sh"))
	if err != nil {
		fmt.Println(err)
		return err
	}
	defer singleDecryptionShell.Close()

	_, err = batchDecryptionShell.WriteString(fmt.Sprintf(BatchDecryptionTemplate, key.KeyHex, util.GetHexStringByByte(key.IV)))
	if err != nil {
		fmt.Println(err)
		return err
	}

	singleDecryptionShell.WriteString(fmt.Sprintf(SingleDecryptionTemplate, key.KeyHex, util.GetHexStringByByte(key.IV)))

	fmt.Println("解密脚本生成成功:", key.KeyHex, util.GetHexStringByByte(key.IV))
	return err
}
